// Decompiled on 周六 2月 22 19:31:49 CST 2025 with Zomboid Decompiler v0.1.3 using Vineflower.
package zombie.ai.states;

import fmod.fmod.FMODManager;
import java.util.HashMap;
import zombie.ai.State;
import zombie.characters.IsoGameCharacter;
import zombie.characters.IsoPlayer;
import zombie.characters.IsoZombie;
import zombie.characters.Stats;
import zombie.characters.Moodles.MoodleType;
import zombie.characters.skills.PerkFactory;
import zombie.core.Core;
import zombie.core.Rand;
import zombie.core.math.PZMath;
import zombie.core.properties.PropertyContainer;
import zombie.core.skinnedmodel.advancedanimation.AnimEvent;
import zombie.iso.IsoDirections;
import zombie.iso.IsoGridSquare;
import zombie.iso.IsoMovingObject;
import zombie.iso.IsoObject;
import zombie.iso.IsoWorld;
import zombie.iso.SpriteDetails.IsoFlagType;
import zombie.iso.SpriteDetails.IsoObjectType;

public final class ClimbOverWallState extends State {
    private static final ClimbOverWallState _instance = new ClimbOverWallState();
    static final Integer PARAM_START_X = 0;
    static final Integer PARAM_START_Y = 1;
    static final Integer PARAM_Z = 2;
    static final Integer PARAM_END_X = 3;
    static final Integer PARAM_END_Y = 4;
    static final Integer PARAM_DIR = 5;
    static final int FENCE_TYPE_WOOD = 0;
    static final int FENCE_TYPE_METAL = 1;
    static final int FENCE_TYPE_METAL_BARS = 2;

    public static ClimbOverWallState instance() {
        return _instance;
    }

    @Override
    public void enter(IsoGameCharacter owner) {
        owner.setIgnoreMovement(true);
        owner.setHideWeaponModel(true);
        HashMap hashMap = owner.getStateMachineParams(this);
        Stats stats = owner.getStats();
        stats.endurance = (float)((double)stats.endurance - zombie.ZomboidGlobals.RunningEnduranceReduce * 1200.0);
        IsoPlayer isoPlayer = (IsoPlayer)owner;
        boolean boolean0 = isoPlayer.isClimbOverWallStruggle();
        if (boolean0) {
            stats = owner.getStats();
            stats.endurance = (float)((double)stats.endurance - zombie.ZomboidGlobals.RunningEnduranceReduce * 500.0);
        }

        boolean boolean1 = isoPlayer.isClimbOverWallSuccess();
        owner.setVariable("ClimbFenceFinished", false);
        owner.setVariable("ClimbFenceOutcome", boolean1 ? "success" : "fail");
        owner.setVariable("ClimbFenceStarted", false);
        owner.setVariable("ClimbFenceStruggle", boolean0);
    }

    @Override
    public void execute(IsoGameCharacter owner) {
        HashMap hashMap = owner.getStateMachineParams(this);
        IsoDirections isoDirections = (IsoDirections)hashMap.get(PARAM_DIR);
        owner.setAnimated(true);
        owner.setDir(isoDirections);
        boolean _boolean = owner.getVariableBoolean("ClimbFenceStarted");
        if (!_boolean) {
            int int0 = (Integer)hashMap.get(PARAM_START_X);
            int int1 = (Integer)hashMap.get(PARAM_START_Y);
            float float0 = 0.15F;
            float float1 = owner.getX();
            float float2 = owner.getY();
            switch (isoDirections) {
                case N:
                    float2 = (float)int1 + float0;
                    break;
                case S:
                    float2 = (float)(int1 + 1) - float0;
                    break;
                case W:
                    float1 = (float)int0 + float0;
                    break;
                case E:
                    float1 = (float)(int0 + 1) - float0;
            }

            float float3 = zombie.GameTime.getInstance().getMultiplier() / 1.6F / 8.0F;
            owner.setX(owner.x + (float1 - owner.x) * float3);
            owner.setY(owner.y + (float2 - owner.y) * float3);
        }
    }

    @Override
    public void exit(IsoGameCharacter owner) {
        owner.clearVariable("ClimbFenceFinished");
        owner.clearVariable("ClimbFenceOutcome");
        owner.clearVariable("ClimbFenceStarted");
        owner.clearVariable("ClimbFenceStruggle");
        owner.setIgnoreMovement(false);
        owner.setHideWeaponModel(false);
        if (owner instanceof IsoZombie) {
            ((IsoZombie)owner).networkAI.isClimbing = false;
        }
    }

    @Override
    public void animEvent(IsoGameCharacter owner, AnimEvent event) {
        if (event.m_EventName.equalsIgnoreCase("PlayFenceSound")) {
            IsoObject isoObject = this.getFence(owner);
            if (isoObject == null) {
                return;
            }

            int _int = this.getFenceType(isoObject);
            long _long = owner.getEmitter().playSoundImpl(event.m_ParameterValue, null);
            owner.getEmitter().setParameterValue(_long, FMODManager.instance.getParameterDescription("FenceTypeHigh"), (float)_int);
        }
    }

    @Override
    public boolean isIgnoreCollide(IsoGameCharacter owner, int fromX, int fromY, int fromZ, int toX, int toY, int toZ) {
        HashMap hashMap = owner.getStateMachineParams(this);
        int int0 = (Integer)hashMap.get(PARAM_START_X);
        int int1 = (Integer)hashMap.get(PARAM_START_Y);
        int int2 = (Integer)hashMap.get(PARAM_END_X);
        int int3 = (Integer)hashMap.get(PARAM_END_Y);
        int int4 = (Integer)hashMap.get(PARAM_Z);
        if (int4 == fromZ && int4 == toZ) {
            int int5 = PZMath.min(int0, int2);
            int int6 = PZMath.min(int1, int3);
            int int7 = PZMath.max(int0, int2);
            int int8 = PZMath.max(int1, int3);
            int int9 = PZMath.min(fromX, toX);
            int int10 = PZMath.min(fromY, toY);
            int int11 = PZMath.max(fromX, toX);
            int int12 = PZMath.max(fromY, toY);
            return int5 <= int9 && int6 <= int10 && int7 >= int11 && int8 >= int12;
        } else {
            return false;
        }
    }

    private IsoObject getClimbableWallN(IsoGridSquare isoGridSquare) {
        IsoObject[] isoObject0 = isoGridSquare.getObjects().getElements();
        int int0 = 0;

        for (int int1 = isoGridSquare.getObjects().size(); int0 < int1; int0++) {
            IsoObject isoObject1 = isoObject0[int0];
            PropertyContainer propertyContainer = isoObject1.getProperties();
            if (propertyContainer != null
                && !propertyContainer.Is(IsoFlagType.CantClimb)
                && isoObject1.getType() == IsoObjectType.wall
                && propertyContainer.Is(IsoFlagType.collideN)
                && !propertyContainer.Is(IsoFlagType.HoppableN)) {
                return isoObject1;
            }
        }

        return null;
    }

    private IsoObject getClimbableWallW(IsoGridSquare isoGridSquare) {
        IsoObject[] isoObject0 = isoGridSquare.getObjects().getElements();
        int int0 = 0;

        for (int int1 = isoGridSquare.getObjects().size(); int0 < int1; int0++) {
            IsoObject isoObject1 = isoObject0[int0];
            PropertyContainer propertyContainer = isoObject1.getProperties();
            if (propertyContainer != null
                && !propertyContainer.Is(IsoFlagType.CantClimb)
                && isoObject1.getType() == IsoObjectType.wall
                && propertyContainer.Is(IsoFlagType.collideW)
                && !propertyContainer.Is(IsoFlagType.HoppableW)) {
                return isoObject1;
            }
        }

        return null;
    }

    private IsoObject getFence(IsoGameCharacter isoGameCharacter) {
        HashMap hashMap = isoGameCharacter.getStateMachineParams(this);
        int int0 = (Integer)hashMap.get(PARAM_START_X);
        int int1 = (Integer)hashMap.get(PARAM_START_Y);
        int int2 = (Integer)hashMap.get(PARAM_Z);
        IsoGridSquare isoGridSquare0 = IsoWorld.instance.CurrentCell.getGridSquare(int0, int1, int2);
        int int3 = (Integer)hashMap.get(PARAM_END_X);
        int int4 = (Integer)hashMap.get(PARAM_END_Y);
        IsoGridSquare isoGridSquare1 = IsoWorld.instance.CurrentCell.getGridSquare(int3, int4, int2);
        if (isoGridSquare0 != null && isoGridSquare1 != null) {
            IsoDirections isoDirections = (IsoDirections)hashMap.get(PARAM_DIR);

            return switch (isoDirections) {
                case N -> this.getClimbableWallN(isoGridSquare0);
                case S -> this.getClimbableWallN(isoGridSquare1);
                case W -> this.getClimbableWallW(isoGridSquare0);
                case E -> this.getClimbableWallW(isoGridSquare1);
                default -> null;
            };
        } else {
            return null;
        }
    }

    private int getFenceType(IsoObject isoObject) {
        if (isoObject.getSprite() == null) {
            return 0;
        } else {
            PropertyContainer propertyContainer = isoObject.getSprite().getProperties();
            String string = propertyContainer.Val("FenceTypeHigh");
            if (string != null) {
                return switch (string) {
                    case "Wood" -> 0;
                    case "Metal" -> 1;
                    case "MetalGate" -> 2;
                    default -> 0;
                };
            } else {
                return 0;
            }
        }
    }

    public void setParams(IsoGameCharacter owner, IsoDirections dir) {
        HashMap hashMap = owner.getStateMachineParams(this);
        int int0 = owner.getSquare().getX();
        int int1 = owner.getSquare().getY();
        int int2 = owner.getSquare().getZ();
        int int3 = int0;
        int int4 = int1;
        switch (dir) {
            case N:
                int4 = int1 - 1;
                break;
            case S:
                int4 = int1 + 1;
                break;
            case W:
                int3 = int0 - 1;
                break;
            case E:
                int3 = int0 + 1;
                break;
            default:
                throw new IllegalArgumentException("invalid direction");
        }

        hashMap.put(PARAM_START_X, int0);
        hashMap.put(PARAM_START_Y, int1);
        hashMap.put(PARAM_Z, int2);
        hashMap.put(PARAM_END_X, int3);
        hashMap.put(PARAM_END_Y, int4);
        hashMap.put(PARAM_DIR, dir);
        IsoPlayer isoPlayer = (IsoPlayer)owner;
        if (isoPlayer.isLocalPlayer()) {
            int int5 = 20;
            int5 += owner.getPerkLevel(PerkFactory.Perks.Fitness) * 2;
            int5 += owner.getPerkLevel(PerkFactory.Perks.Strength) * 2;
            int5 -= owner.getMoodles().getMoodleLevel(MoodleType.Endurance) * 5;
            int5 -= owner.getMoodles().getMoodleLevel(MoodleType.HeavyLoad) * 8;
            if (owner.getTraits().contains("Emaciated") || owner.Traits.Obese.isSet() || owner.getTraits().contains("Very Underweight")) {
                int5 -= 25;
            }

            if (owner.getTraits().contains("Underweight") || owner.getTraits().contains("Overweight")) {
                int5 -= 15;
            }

            IsoGridSquare isoGridSquare = owner.getCurrentSquare();
            if (isoGridSquare != null) {
                for (int int6 = 0; int6 < isoGridSquare.getMovingObjects().size(); int6++) {
                    IsoMovingObject isoMovingObject = (IsoMovingObject)isoGridSquare.getMovingObjects().get(int6);
                    if (isoMovingObject instanceof IsoZombie) {
                        if (((IsoZombie)isoMovingObject).target == owner && ((IsoZombie)isoMovingObject).getCurrentState() == AttackState.instance()) {
                            int5 -= 25;
                        } else {
                            int5 -= 7;
                        }
                    }
                }
            }

            int5 = Math.max(0, int5);
            boolean boolean0 = Rand.NextBool(int5 / 2);
            if ("Tutorial".equals(Core.GameMode)) {
                boolean0 = false;
            }

            boolean boolean1 = !Rand.NextBool(int5);
            isoPlayer.setClimbOverWallStruggle(boolean0);
            isoPlayer.setClimbOverWallSuccess(boolean1);
        }
    }
}
